/* Copyright (C) 2011. ChengDu Unicon system, All Rights Reserved */

/*""FILE COMMENT""******************************* Technical reference data ****
* File Name	: cam.c
* Version 	: 1.00
* Device 	: SH72543
* Tool Chain 	: 
* H/W Platform	: 
* Description 	: 
******************************************************************************/

/******************************************************************************
* History 	: 11.08.2011 Ver. 1.00 First Release
*		: 
*FILE COMMENT END*********************************************************/

#include <include.h>

ST_CAM camData;

void CamMeasureISR( void );
void CamBufInit( void );


/**************************************************************************
 *Function   : CamInit       
 *Description:                                                     
 *Input      :                              
 *Output     :                              
 *Return     : 
 *G Variable :                              
 *Notes      :                                   
 **************************************************************************/
void CamInit( const ST_CAM_HW_SET *const camHWInitVal )
{
  /* Crank IO Init */
  PORTA.DR.BIT.DR12   = 1; //Output High level
  PORTA.IOR.BIT.IOR12 = 1; //The PA12 is set to output
  PORTA.DR.BIT.DR7    = 1; //Disable pullup of sensor input 
  PORTA.IOR.BIT.IOR7  = 1; //The PA7 is set to output
  PORTE.CR2.BIT.MD12  = 1; //PE12 is set to TOE12 output
  PORTE.IR.BIT.IR12   = 0; //Not inverted
  PORTE.CR1.BIT.MD1   = 1; //PE1 is set to PIA01 input
  
  /* Init TOE12, Be used to set offset value*/
  ATUE.TSTRE.BIT.STRE1   = 1; //Timer Start Register E1
  /* Timer Control Register, Select the counter clock of prescaler E from clock-bus lines 0 to 5 */
  ATUE.SUBBLOCK[1].TCRE.BIT.CKSELE  = 0; /* Clock-bus line 0 */
  /* Timer Output Control Register, 0:Signal is output as is on PWM output pin
   *                                1:Inverted signal is output on PWM output pin */
  ATUE.SUBBLOCK[1].TOCRE.BIT.TONEE2     = 0;   
  ATUE.SUBBLOCK[1].TIERE.BIT.CMEE2      = 0; //Timer Interrupt Enable Register
  ATUE.SUBBLOCK[1].RLDCRE.BIT.RLDENE2   = 1; //Reload Control Register
  ATUE.SUBBLOCK[1].TSRE.BIT.OVFE2       = 0; //Timer Status Register
  ATUE.SUBBLOCK[1].TSRE.BIT.CMFE2       = 0; //Timer Status Register
  ATUE.SUBBLOCK[1].PSCRE.BIT.PSCE       = 3; //Prescaler Register E, From H'0 to H'7 
  ATUE.SUBBLOCK[1].CRLDE[2]     = camHWInitVal->pwmCycle; /* Cycle Register Value = (E Frequre/Cycle Set Value) */
  ATUE.SUBBLOCK[1].DRLDE[2]     = camHWInitVal->pwmDuty;  /* Duty Register Value = (Cycle/100.00%)*Duty Set Value */ 
  ATUE.SUBBLOCK[1].TCNTE[2]             = 0; //Clear Timer Counter E
  ATUE.SUBBLOCK[1].SSTRE.BIT.SSTRE2     = 1; //Start  
  
  /* Init Timer A01 */
  ATUA.TCNTA  = 0; //Free-Running counter A is initialized to 0
  ATUA.TCRA.BIT.CKSELA   = 0; //Clock-bus line 0
  ATUA.TCRA.BIT.EVOSEL2A = 0; //TIA01 is selected as event output2A
  ATUA.TCRA.BIT.EVOSEL2B = 0; //TIA01 is selected as event output2B
  ATUA.TIOR1A.BIT.IOA1   = camHWInitVal->edgeType; //TCNTA captured edge of TIA01   
  ATUA.TSRA.BIT.OVFA     = 0; //Clear Overflow Flag
  ATUA.TSRA.BIT.ICFA1    = 0; //Clear Input Capture Flag A1
  ATUA.TIERA.BIT.ICEA1   = 1; //Enables a request of input capture interrupt A1
  ATUA.ICRA1 = 0;            //ICRA1 is initialized to 0
  
  /* CAM input noise filter Set */
  ATUA.TIOR2A.BIT.NCKA1 = 0; //Noise canceler count clock is selected as the signal for counting by NCNTA1
  ATUA.TIOR2A.BIT.NCEA1 = 1; //Noise cancelers for TIA are enabled
  ATUA.NCNTA1 = 0;           //Noise canceler counter A0 is initialized to 0
  ATUA.NCRA1  = camHWInitVal->minPW * 1000 / 3200; //Init the noise canceler register A0, Set time / (P Clock / 128)
  
  //Timer D12 is not used, The input capture by OSBRD1 enable is initialized by injection init(timer D)
  /* Init TimerD12 as CAM measure, Disable TOD12A and TOD12B output */
//  ATUD.SUBBLOCKA[1].TCRD.BIT.OBRED = 0; //Enable input capture by OSBRD1
//  ATUD.SUBBLOCKA[1].TCRD.BIT.C2CED = 0; //TCNT2D1 clearing signal from timer B is disabled
//  ATUD.SUBBLOCKA[1].TCRD.BIT.C1CED = 1; //TCNT1D1 clearing signal from timer B is enabled
//  ATUD.SUBBLOCKA[1].TCRD.BIT.CKSEL2D = 0; //TCNT2Dn is driven by clock-bus line 0
//  ATUD.SUBBLOCKA[1].TCRD.BIT.CKSEL1D = 5; //TCNT2Dn is driven by clock-bus line 5
//  ATUD.SUBBLOCKA[1].TCRD.BIT.DCSELD  = 0; //DCNTD1m is driven by clock-bus line 5
//  ATUD.SUBBLOCKB[1].TIOR1D.BIT.OSSD2 = 0; //Output level on TOD12A is not changed
//  ATUD.SUBBLOCKB[1].TIOR1D.BIT.IOAD2 = 0; //TOD12A Compare match is not performed
//  ATUD.SUBBLOCKB[1].TIOR2D.BIT.IOBD2 = 0; //TOD12B Compare match is not performed
//  ATUD.SUBBLOCKB[1].DSTRD.BIT.DSTD2  = 0; //DCNTD12 is no operation
//  ATUD.SUBBLOCKB[1].DCRD.BIT.TRGSELD2 = 0; //DCNTD12 is no trigger
//  ATUD.SUBBLOCKB[1].TSRD.BIT.OVF2D    = 0; //TCNT2D1 has not overflowed
//  ATUD.SUBBLOCKB[1].TSRD.BIT.OVF1D    = 0; //TCNT1D1 has not overflowed
//  ATUD.SUBBLOCKB[1].TSRD.BIT.UDFD2    = 0; //DCNTD12 has not underflowed
//  ATUD.SUBBLOCKB[1].TSRD.BIT.CMFAD2   = 0; //Compare match A12 has not occurred
//  ATUD.SUBBLOCKB[1].TSRD.BIT.CMFBD2   = 0; //Compare match B12 has not occurred
//  ATUD.SUBBLOCKB[1].TIERD.BIT.UDED2   = 0; //1; //D12 underflow interrupt is enable
//  ATUD.SUBBLOCKB[1].TIERD.BIT.CMEAD2  = 0; //1; //D12A compare match interrupt is enable
//  ATUD.SUBBLOCKB[1].TIERD.BIT.CMEBD2  = 0; //D12B compare match interrupt is disable
//  ATUD.SUBBLOCKA[1].CMPOD.BIT.CMPBD2  = 0; //Compare match B12 pulse is not output
//  ATUD.SUBBLOCKA[1].CMPOD.BIT.CMPAD2  = 0; //Compare match A12 pulse is not output
  
//  ATUD.SUBBLOCKB[1].OCRD[2] = camHWInitVal->measureCycle; //Output compare register D12
//  ATUD.SUBBLOCKB[1].GRD[2]  = 0; //General register D12
  
  /* Register Interrupt into interrupt vector table */
  BSP_VectAdd( CamMeasureISR, ATUA_ICIA1 );
  
//  ATUD.TSTRD.BIT.STRD0  = 1; //Enable TCNT1Dn,TCNT2Dn,and DCNTDnm
}  

/**************************************************************************
 *Function   : CamMeasureISRHandler      
 *Description:                                                
 *Input      :                              
 *Output     :                              
 *Return     : 
 *G Variable :                              
 *Notes      :                                   
 **************************************************************************/
void CamMeasureISRHandler( void )
{
  ST_CAM *camBuf;
  
  camBuf = &camData;
  
  ATUA.TSRA.BIT.ICFA1 = 0; //Clear Input Capture Flag A1
  ATUA.TCNTA = 0; //Clear Free-running counter A
  
  /* Put speed data */
  if (camBuf->speed.bufCnt < CAM_SPEED_BUF_SIZE)
  {
    *camBuf->speed.inPtr++ = ATUA.ICRA1; //Put data and pointer add 1
    camBuf->speed.bufCnt++; //buffer count add 1
    
    if (&camBuf->speed.data[CAM_SPEED_BUF_SIZE] <= camBuf->speed.inPtr)
    {
      camBuf->speed.inPtr = &camBuf->speed.data[0];
    }
    
    OSSemPost( camBuf->speed.dataRdySem ); //Post semaphore
  }
  
  /* Put angle data */
  if (camBuf->angle.bufCnt < CAM_ANGLE_BUF_SIZE)
  {
    *camBuf->angle.inPtr++ = ATUA.ICRA1; //Put data and pointer add 1
    camBuf->angle.bufCnt++; //buffer count add 1
    
    if (&camBuf->angle.data[CAM_ANGLE_BUF_SIZE] <= camBuf->angle.inPtr)
    {
      camBuf->angle.inPtr = &camBuf->angle.data[0];
    }
    
    OSSemPost( camBuf->angle.dataRdySem ); //Post semaphore
  }  
}

/**************************************************************************
 *Function   : CamBufInit      
 *Description:                                                
 *Input      :                              
 *Output     :                              
 *Return     : 
 *G Variable :                              
 *Notes      :                                   
 **************************************************************************/
void CamBufInit( void )
{
  ST_CAM *camBuf;
  
  camBuf = &camData;
  
  /* Init speed buffer */
  camBuf->speed.bufCnt = 0; //Clear buffer count
  camBuf->speed.inPtr  = &camBuf->speed.data[0]; //Init input pointer
  camBuf->speed.outPtr = &camBuf->speed.data[0]; //Init output pointer
  camBuf->speed.dataRdySem = OSSemCreate( 0 );   //Create a speed data ready semaphore
  
  /* Init angle buffer */
  camBuf->angle.bufCnt = 0; //Clear buffer count
  camBuf->angle.inPtr  = &camBuf->angle.data[0]; //Init input pointer
  camBuf->angle.outPtr = &camBuf->angle.data[0]; //Init output pointer
  camBuf->angle.dataRdySem = OSSemCreate( 0 );   //Create a angle data ready semaphore
  
//  camBuf->syncToothSem = OSSemCreate( 0 );       //Create a sync tooth ready semaphore
}